package trimble

import (
	"dgo/goutils/gnss"
	"dgo/goutils/utils"
	"fmt"
	"math"
)

const MAXCHN = 35 // 140
const MAXSYS = 4

const SYSGPS = 0 // 0  ~ 35
const SYSGLN = 1 // 35 ~ 70
const SYSBD2 = 2 // 70 ~ 105
const SYSGAL = 3 // 105 ~ 140

const NO_GLN_CHANEL = 2

const PI = 3.14

//type stTime struct {
//	gpsWeek   uint64
//	gpsSecond uint64
//}

type gpsObs struct {
	ClockError [4]float64 //  Inter-System	Clock	Offset	Block
	//prn        [MAXSYS * MAXCHN]int
	//channel    [MAXSYS * MAXCHN]int
	//elve       [MAXSYS * MAXCHN]float64
	//azim       [MAXSYS * MAXCHN]float64

	CA [MAXSYS * MAXCHN]float64

	//P1  [MAXSYS * MAXCHN]float64
	//L1  [MAXSYS * MAXCHN]float64
	//D1  [MAXSYS * MAXCHN]float64
	//sn1 [MAXSYS * MAXCHN]float64
	//
	//P2  [MAXSYS * MAXCHN]float64
	//L2  [MAXSYS * MAXCHN]float64
	//D2  [MAXSYS * MAXCHN]float64
	//sn2 [MAXSYS * MAXCHN]float64
	//
	//P3  [MAXSYS * MAXCHN]float64
	//L3  [MAXSYS * MAXCHN]float64
	//D3  [MAXSYS * MAXCHN]float64
	//sn3 [MAXSYS * MAXCHN]float64
	//
	//P4  [MAXSYS * MAXCHN]float64
	//L4  [MAXSYS * MAXCHN]float64
	//D4  [MAXSYS * MAXCHN]float64
	//sn4 [MAXSYS * MAXCHN]float64
	//
	//P5  [MAXSYS * MAXCHN]float64
	//L5  [MAXSYS * MAXCHN]float64
	//D5  [MAXSYS * MAXCHN]float64
	//sn5 [MAXSYS * MAXCHN]float64

	//stTime
}

type TrimbleRT27 struct {
	ObsN uint32
	gpsObs
}

/*
*

	bufl : 44
*/
func (this *TrimbleRT27) DecodeObs(week, tow uint32, buf []byte, transVars *gnss.GnssYObsTransVarCollect, obs *gnss.YObsSignal) error {
	trackval := gnss.U4FromBuf(buf[40:])
	fmt.Println(trackval)
	return nil
}

func (this *TrimbleRT27) DecodeBuf(buf []byte, onobs func(idx int, yobs *gnss.YObsSignal, err error) bool) error {
	// 1 (byte) BLOCK LENGTH
	byteN := 0
	//nBlockLen := utils.GetBitU8(buf[byteN:],0,8)
	//fmt.Println("nBlockLen", nBlockLen)
	byteN++

	// 2 (short) WEEK NUMBER
	weeks := utils.GetBitU64(buf[byteN:], 0, 16)
	if weeks < 1024 || weeks > 1024*10 {
		return nil
	}
	//this.gpsObs.stTime.gpsWeek = weeks
	//fmt.Println("weeks", weeks)
	byteN += 2

	// 4 (long) RECEIVER TIME
	//lTime := utils.GetBitU64(buf[byteN:], 0, 32)
	//this.gpsObs.stTime.gpsSecond = lTime / 1000.0
	//fmt.Println("lTime", lTime)
	byteN += 4

	// 3 (integer3) CLOCK OFFSET
	clkoffset := float64(utils.GetBitI32(buf[byteN:], 0, 24))
	this.gpsObs.ClockError[SYSGPS] = (clkoffset / math.Pow(2.0, 19.0)) / 1000.0 // sysgps
	byteN += 3

	// 1 (byte) NUMBER SVS

	nPrn := int(buf[byteN])
	byteN++

	// 1 (byte) EPOCH FLAGS
	//e0 :=  utils.GetBitU8(buf[byteN:],7,1)
	e1 := utils.GetBitU8(buf[byteN:], 6, 1)
	//e23 :=  utils.GetBitU8(buf[byteN:],4,2)
	e4 := utils.GetBitU8(buf[byteN:], 3, 1)
	e5 := utils.GetBitU8(buf[byteN:], 2, 1) //第5位存在系统间时钟偏移
	//e6 :=  utils.GetBitU8(buf[byteN:],1,1)
	//e7 :=  utils.GetBitU8(buf[byteN:],0,1)
	byteN++

	// // 3 (integer3) GPS GLONASS TIME OFFSET [Optional]
	if e1 != 0 {
		//lGPS_GLONASS_Offset := utils.GetBitI32(buf[byteN:], 0, 24)
		//fmt.Println("lGPS_GLONASS_Offset", lGPS_GLONASS_Offset)
		byteN += 3
	}
	//1 (byte)RAIM	INFO[if	bit	4	of 	EPOCH	FLAGS	is	set]
	if e4 != 0 {
		//SKIPBITS(8); //1 (byte)
		byteN++
	}
	//Inter-System	Clock	Offset	Block:	Available	if	bit	5 is	set	in	EPOCH	FLAGS
	nPreHeader := 5
	if e5 != 0 {
		//1 (byte) BLOCK LENGTH
		nPreHeader = int(utils.GetBitU8(buf[byteN:], 0, 8))
		byteN++
		//1 (byte)	INTER - SYSTEM CLOCK	OFFSET 	HEADER
		InterClkHeader := int(utils.GetBitU8(buf[byteN:], 0, 8))
		byteN++

		//iSysRef := InterClkHeader & 0x07 //0-3 参考卫星系统 0 GPS 1 SBAS  2 GLONASS 3 GALILIO 4 QZSS 5 BDS
		//fmt.Println("iSysRef", iSysRef)
		nSysOffSet := (InterClkHeader >> 4) & 0x07 //4-6 几个卫星导航系统

		for i := 0; i < nSysOffSet; i++ {
			//GETBITS(InterClkInfo, 8);
			InterClkInfo := int(utils.GetBitU8(buf[byteN:], 0, 8))
			iSystem := InterClkInfo & 0x07        // 0 - 3 当前卫星系统 0 GPS 1 SBAS  2 GLONASS 3 GALILIO 4 QZSS 5 BDS
			nMBytes := (InterClkInfo >> 4) & 0x07 // 数据长度
			byteN++

			//GETBITSSIGN(llClockOffset, nMBytes * 8);
			llClockOffset := float64(utils.GetBitI32(buf[byteN:], 0, nMBytes*8))
			clkcOffset := (llClockOffset / math.Pow(2.0, 28)) / 1000.0
			byteN += nMBytes

			if iSystem == 2 {
				this.gpsObs.ClockError[SYSGLN] = this.gpsObs.ClockError[SYSGPS] + clkcOffset
			}
			if iSystem == 5 {
				this.gpsObs.ClockError[SYSBD2] = this.gpsObs.ClockError[SYSGPS] + clkcOffset
			}
		}
		nPreHeader = 5
	}

	nGps := 0
	nGlonass := 0
	nBD2 := 0
	nGal := 0

	var PrnList [MAXSYS * MAXCHN]int
	var PrnType [MAXSYS * MAXCHN]int
	//blockType := [MAXSYS * MAXCHN]int{0}
	//TrackType := [MAXSYS * MAXCHN]int{0}

	var obs gnss.YObsSignal
	for i := 0; i < nPrn; i++ {
		obs.Reset()
		if i >= MAXSYS*MAXCHN {
			break
		}
		curLen := 0
		nOnePrnHeaderLen := 0
		if nPreHeader == 5 {
			//1 (byte) BLOCK LENGTH
			nOnePrnHeaderLen = int(utils.GetBitU8(buf[byteN:], 0, 8))
			byteN++
		} else {
			nOnePrnHeaderLen = nPreHeader
			nPreHeader = 5
		}
		if nOnePrnHeaderLen != 12 && nOnePrnHeaderLen != 8 && nOnePrnHeaderLen != 28 {
			return nil
		}
		curLen++

		svId := 0
		svType := 0
		//svChannel := 0
		nBlockLen2 := 0
		svFlag := 0
		//pseudo_iode := 0

		//fmt.Println("pseudo_iode",pseudo_iode)
		//elev := 0
		//azim := 0

		if curLen < nOnePrnHeaderLen {
			curLen++
			//	1 (byte) SV ID
			svId = int(utils.GetBitU8(buf[byteN:], 0, 8))
			//fmt.Println("svId", svId)

			byteN++
		}

		if curLen < nOnePrnHeaderLen {
			curLen++
			//1 (byte) SV TYPE
			svType = int(utils.GetBitU8(buf[byteN:], 0, 8))
			byteN++
			svType = svType & 0x1f

			//fmt.Printf("svType:%d-svId:%d\n", svType, svId)
			obs.NaviSys = byte(svType)
			PrnType[i] = svType // Bits	6-7:	ANTENNA	indicates	the	antenna/receiver	which	recorded	this	bservation	(applicable	to	the	BD982):
			PrnList[i] = svId

			if svType == 0 {
				if nGps < MAXCHN {
					//this.gpsObs.prn[nGps] = svId
					//this.gpsObs.channel[SYSGPS*MAXCHN+nGps] = 0
					nGps++
				}
			} else if svType == 2 {
				if nGlonass < MAXCHN {
					//this.gpsObs.prn[SYSGLN*MAXCHN+nGlonass] = svId
					//this.gpsObs.channel[SYSGLN*MAXCHN+nGlonass] = NO_GLN_CHANEL
					nGlonass++
				}
			} else if svType == 7 || svType == 10 {
				if nBD2 < MAXCHN {
					//this.gpsObs.prn[SYSBD2*MAXCHN+nBD2] = svId
					//this.gpsObs.channel[SYSBD2*MAXCHN+nBD2] = 0
					nBD2++
				}
			} else if svType == 3 {
				if nGal < MAXCHN {
					//this.gpsObs.prn[SYSGAL*MAXCHN+nGal] = svId
					//this.gpsObs.channel[SYSGAL*MAXCHN+nGal] = 0
					nGal++
				}
			}
		}

		if curLen < nOnePrnHeaderLen {
			curLen++
			//1 (byte) SV CHANNEL
			//svChannel = int(utils.GetBitI8(buf[byteN:], 0, 8))
			byteN++
			//if svType == 0 && nGps > 0 {
			//	this.gpsObs.channel[nGps-1] = svChannel
			//} else if svType == 2 && nGlonass > 0 {
			//	this.gpsObs.channel[SYSGLN*MAXCHN+nGlonass-1] = svChannel
			//} else if (svType == 7 || svType == 10) && nBD2 > 0 {
			//	this.gpsObs.channel[SYSBD2*MAXCHN+nBD2-1] = 0
			//} else if svType == 3 && nGal > 0 {
			//	this.gpsObs.channel[SYSGAL*MAXCHN+nGal-1] = svChannel
			//}
		}
		if curLen < nOnePrnHeaderLen {
			curLen++
			//	1 (byte) NUMBER OF BLOCKS
			nBlockLen2 = int(buf[byteN])
			byteN++
		}
		if curLen < nOnePrnHeaderLen {
			curLen++
			//	1 (byte) ELEVATION
			//elev = int(buf[byteN])
			byteN++

			//if svType == 0 && nGps > 0 {
			//	this.gpsObs.elve[nGps-1] = float64(elev) * PI / 180
			//} else if svType == 2 && nGlonass > 0 {
			//	this.gpsObs.elve[SYSGLN*MAXCHN+nGlonass-1] = float64(elev) * PI / 180
			//} else if (svType == 7 || svType == 10) && nBD2 > 0 {
			//	this.gpsObs.elve[SYSBD2*MAXCHN+nBD2-1] = float64(elev) * PI / 180
			//} else if svType == 3 && nGal > 0 {
			//	this.gpsObs.elve[SYSGAL*MAXCHN+nGal-1] = float64(elev) * PI / 180
			//}
		}
		if curLen < nOnePrnHeaderLen {
			curLen++
			//	1 (byte) AZIMUTH
			//azim = int(utils.GetBitU8(buf[byteN:], 0, 8))
			byteN++

			//if svType == 0 && nGps > 0 {
			//	this.gpsObs.azim[nGps-1] = float64(azim) * 2 * PI / 180
			//} else if svType == 2 && nGlonass > 0 {
			//	this.gpsObs.azim[SYSGLN*MAXCHN+nGlonass-1] = float64(azim) * 2 * PI / 180
			//} else if (svType == 7 || svType == 10) && nBD2 > 0 {
			//	this.gpsObs.azim[SYSBD2*MAXCHN+nBD2-1] = float64(azim) * 2 * PI / 180
			//} else if svType == 3 && nGal > 0 {
			//	this.gpsObs.azim[SYSGAL*MAXCHN+nGal-1] = float64(azim) * 2 * PI / 180
			//}
		}
		if curLen < nOnePrnHeaderLen {
			//	1 (byte) SV FLAGS
			curLen++
			svFlag = int(utils.GetBitU8(buf[byteN:], 0, 8))
			byteN++
		}
		//svFlag2 := 0
		if svFlag>>7 == 1 {
			curLen++
			//svFlag2 = int(utils.GetBitU8(buf[byteN:],0,8))
			byteN++
		}
		//fmt.Println("svFlag2",svFlag2)
		if svFlag>>6 == 1 {
			curLen += 4
			//   4 (byte) Pseudo-IODE [Optional] (A change in this value indicates an ephemeris update)
			//pseudo_iode = int(utils.GetBitU64(buf[byteN:],0,32))
			byteN += 4
		}
		if curLen < nOnePrnHeaderLen {
			//SKIPBITS((nOnePrnHeaderLen - curLen) * 8);
			byteN += nOnePrnHeaderLen - curLen
		}
		for j := 0; j < nBlockLen2; j++ {
			curLen := 0
			nBlockLen3 := 0
			blockType := 0
			TrackType := 0
			snr := 0
			lca := 0
			l64phase := 0
			//cySlipCount := 0
			dlca := 0
			measFlag := 0
			measFlag2 := 0
			lDoppler := 0
			//measFlag3 := 0

			//fmt.Println("cySlipCount",cySlipCount,"measFlag3",measFlag3)
			curLen++
			//1 (byte) BLOCK LENGTH

			nBlockLen3 = int(utils.GetBitU8(buf[byteN:], 0, 8))
			//fmt.Println(nBlockLen3)
			byteN++
			//fmt.Println("********************",nBlockLen3)
			if curLen < nBlockLen3 {
				curLen++
				//GETBITS(blockType, 8) //1 (byte) BLOCK TYPE 表示该观测的SV频段（见下表）
				blockType = int(utils.GetBitU8(buf[byteN:], 0, 8))
				//fmt.Println("blockType", blockType)
				byteN++
			}
			if curLen < nBlockLen3 {
				curLen++
				//GETBITS(TrackType, 8) //1 (byte) TRACK TYPE 表示本次观测中跟踪的SV信号（见下表）
				TrackType = int(utils.GetBitU8(buf[byteN:], 0, 8))
				//fmt.Println("TrackType", TrackType)
				byteN++
			}

			if curLen < nBlockLen3 {
				curLen += 2
				//GETBITS(snr, 16) //2 (word) SNR
				snr = int(utils.GetBitI16(buf[byteN:], 0, 16))
				//snr = int(utils.GetBitU64(buf[byteN:], 0, 16))
				byteN += 2
			}
			if curLen < nBlockLen3 {
				if blockType == 0 /* && nBlockLen3 >= 20*/ {
					curLen += 4
					//GETBITS(lca, 32) //4 (integer4) PSEUDORANGE or 2 (real2) DIFFERENTIAL PSEUDORANGE
					lca = int(utils.GetBitU64(buf[byteN:], 0, 32))
					byteN += 4
				} else if blockType == 6 /*&& nBlockLen3 >= 20*/ {
					curLen += 4
					//GETBITS(lca, 32) //4 (integer4) PSEUDORANGE or 2 (real2) DIFFERENTIAL PSEUDORANGE
					lca = int(utils.GetBitU64(buf[byteN:], 0, 32))
					byteN += 4
				} else {
					curLen += 2
					//GETBITSSIGN(dlca, 16) //4 (integer4) PSEUDORANGE or 2 (real2) DIFFERENTIAL PSEUDORANGE
					dlca = int(utils.GetBitI32(buf[byteN:], 0, 16))
					byteN += 2
				}
				//if(TrackType ==0 || TrackType == 26)
				//{
				//}
				//else if(TrackType !=0)
				//{
				//}
			}
			if curLen < nBlockLen3 {
				curLen += 6
				//GETBITSSIGN(l64phase, 48) //6 (integer6) PHASE
				l64phase = int(utils.GetBitI64(buf[byteN:], 0, 48))
				byteN += 6
			}

			if curLen < nBlockLen3 {
				curLen++
				//GETBITS(cySlipCount, 8) //1 (byte) CYCLE SLIP COUNT
				//cySlipCount = int(utils.GetBitU8(buf[byteN:],0,8))
				byteN++
			}
			if curLen < nBlockLen3 {
				curLen++
				//GETBITS(measFlag, 8) //1 (byte) MEASUREMENT FLAGS
				measFlag = int(utils.GetBitU8(buf[byteN:], 0, 8))
				byteN++
			}

			//bHalfCycle := (measFlag >> 4) & 0x01
			bHaveDopler := (measFlag >> 2) & 0x01

			// 			if(bHalfCycle == 1)
			// 			{
			// 				int ddBreak = 0;
			// 			}

			//bPositive := (measFlag >> 6) & 0x01

			// 			if(bPositive == 1)
			// 			{
			// 				int ddBreak = 0;
			// 			}

			if measFlag>>7 == 1 {
				curLen++
				//GETBITS(measFlag2, 8) //1 (byte) MEASUREMENT FLAGS
				measFlag2 = int(utils.GetBitU8(buf[byteN:], 0, 8))
				byteN++
			}

			bOverFlow := measFlag2 >> 1 & 0x01
			//bOverFlowDiff := measFlag2 & 0x01
			//if(bOverFlowDiff == 1)
			//{
			//	int ddBreak = 0;
			//
			//}
			if measFlag2>>7 == 1 {
				curLen++
				//GETBITS(measFlag3, 8) //1 (byte) MEASUREMENT FLAGS
				//measFlag3 = int(utils.GetBitU8(buf[byteN:],0,8))
				byteN++
			}

			if curLen+3 <= nBlockLen3 && bHaveDopler == 1 {
				curLen += 3
				//GETBITSSIGN(lDoppler, 24) //3 (integer3) DOPPLER [Optional]
				lDoppler = int(utils.GetBitI32(buf[byteN:], 0, 24))
				byteN += 3
				//if(blockType == 0)
				//{
				//	gpsObs.D1[i] = 1.0*lDoppler/pow(2.0,6);
				//}
				//if(blockType == 1)
				//{
				//	gpsObs.D2[i] = 1.0*lDoppler/pow(2.0,6);
				//}
			}

			//			else if svId == 14 && svType == 2 && j == 1 {
			//				byteN += 19 - curLen
			//			} else if svId == 9 && svType == 0 && j == 2 {
			//				byteN += 19 - curLen
			//			}
			if curLen != nBlockLen3 {
				//SKIPBITS((nBlockLen3 - curLen)*8);
				byteN += nBlockLen3 - curLen
			}

			if blockType == 0 { //0: L1 ( GPS/GLONASS/Galileo/SBAS)
				if svType == 0 { //gps  && nGps > 0
					if TrackType == 0 {
						this.gpsObs.CA[nGps-1] = 1.0 * float64(lca) / math.Pow(2.0, 7)
					}
					//this.gpsObs.P1[nGps-1] = this.gpsObs.CA[nGps-1]
					//this.gpsObs.L1[nGps-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D1[nGps-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn1[nGps-1] = float32(snr / 10.0)

					obs.NaviSys = gnss.SYS_GPS
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_GPS_SIGN_L1_1C

					obs.PsV = 1.0 * float64(lca) / math.Pow(2.0, 7)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				} else if svType == 2 { //glonass   && nGlonass > 0
					if TrackType == 0 { // SV信号
						this.gpsObs.CA[SYSGLN*MAXCHN+nGlonass-1] = 1.0 * float64(lca) / math.Pow(2.0, 7)
						//this.gpsObs.P1[SYSGLN*MAXCHN+nGlonass-1] = this.gpsObs.CA[SYSGLN*MAXCHN+nGlonass-1]
						//this.gpsObs.L1[SYSGLN*MAXCHN+nGlonass-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
						////double ddL1=gpsObs.L1[SYSGLN*MAXCHN+nGlonass-1];
						//this.gpsObs.D1[SYSGLN*MAXCHN+nGlonass-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
						//this.gpsObs.sn1[SYSGLN*MAXCHN+nGlonass-1] = float32(snr / 10.0)

						obs.NaviSys = gnss.SYS_GLO
						obs.SatId = byte(svId)
						obs.SigId = gnss.YOBS_GLO_SIGN_G1_1C

						obs.PsV = this.gpsObs.CA[SYSGLN*MAXCHN+nGlonass-1]
						obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
						obs.Cnr = float32(snr / 10.0)
						obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

						//fmt.Printf("Sys:%f-SatId:%f-SigId:%f\n",obs.NaviSys,obs.SatId,obs.SigId)
						//fmt.Printf("PsV:%f-PhV:%f-Cnr:%f-Doppler:%f\n",obs.PsV,obs.PhV,obs.Cnr,obs.Doppler)
						if !onobs(i+1, &obs, nil) {
							break
						}
					} else if TrackType != 0 { // SV信号
						//this.gpsObs.P2[SYSGLN*MAXCHN+nGlonass-1] = this.gpsObs.CA[SYSGLN*MAXCHN+nGlonass-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
						//this.gpsObs.L2[SYSGLN*MAXCHN+nGlonass-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
						//this.gpsObs.D2[SYSGLN*MAXCHN+nGlonass-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
						//this.gpsObs.sn2[SYSGLN*MAXCHN+nGlonass-1] = float32(snr / 10.0)

						if nBlockLen2 == 2 {
							obs.NaviSys = gnss.SYS_GLO
							obs.SatId = byte(svId)
							obs.SigId = gnss.YOBS_GLO_SIGN_G2_2P

							obs.PsV = this.gpsObs.CA[SYSGLN*MAXCHN+nGlonass-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
							obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
							obs.Cnr = float32(snr / 10.0)
							obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

							//fmt.Printf("Sys:%d-SatId:%d-SigId:%d\n",obs.NaviSys,obs.SatId,obs.SigId)
							//fmt.Printf("PsV:%f-PhV:%f-Cnr:%f-Doppler:%f\n",obs.PsV,obs.PhV,obs.Cnr,obs.Doppler)
							if !onobs(i+1, &obs, nil) {
								break
							}
						}
					}
				} else if svType == 7 || svType == 10 { //BDS
					//this.gpsObs.P4[SYSBD2*MAXCHN+nBD2-1] = this.gpsObs.CA[SYSBD2*MAXCHN+nBD2-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L4[SYSBD2*MAXCHN+nBD2-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D4[SYSBD2*MAXCHN+nBD2-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn4[SYSBD2*MAXCHN+nBD2-1] = float32(snr / 10.0)
					//this.gpsObs.channel[SYSBD2*MAXCHN+nBD2-1] = 1

					obs.NaviSys = gnss.SYS_BD
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_BDS_SIGN_B1C_1P

					obs.PsV = this.gpsObs.CA[SYSBD2*MAXCHN+nBD2-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				} else if svType == 3 { //  1575.42 E1 && nGal > 0
					this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1] = 1.0 * float64(lca) / math.Pow(2.0, 7)
					//this.gpsObs.P1[SYSGAL*MAXCHN+nGal-1] = this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1]
					//this.gpsObs.L1[SYSGAL*MAXCHN+nGal-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D1[SYSGAL*MAXCHN+nGal-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn1[SYSGAL*MAXCHN+nGal-1] = float32(snr / 10.0)

					obs.NaviSys = gnss.SYS_GAL
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_GAL_SIGN_E1_1X

					obs.PsV = 1.0 * float64(lca) / math.Pow(2.0, 7)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				}
			} else if blockType == 1 { // L2 (GPS/GLONASS)
				if svType == 0 && nGps > 0 { // GPS
					//this.gpsObs.P2[nGps-1] = this.gpsObs.CA[nGps-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L2[nGps-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D2[nGps-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn2[nGps-1] = float32(snr / 10.0)
					obs.NaviSys = gnss.SYS_GPS
					obs.SatId = byte(svId)
					if TrackType == 0 {
						obs.SigId = gnss.YOBS_GPS_SIGN_L2_2C
					} else if TrackType == 5 {
						obs.SigId = gnss.YOBS_GPS_SIGN_L2_2X
					} else if TrackType == 2 {
						obs.SigId = gnss.YOBS_GPS_SIGN_L2_2W
					} else {
						obs.SigId = gnss.YOBS_GPS_SIGN_L2_2C
					}
					obs.PsV = this.gpsObs.CA[nGps-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				} else if svType == 2 && nGlonass > 0 { //
					//this.gpsObs.P2[SYSGLN*MAXCHN+nGlonass-1] = this.gpsObs.CA[SYSGLN*MAXCHN+nGlonass-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L2[SYSGLN*MAXCHN+nGlonass-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D2[SYSGLN*MAXCHN+nGlonass-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn2[SYSGLN*MAXCHN+nGlonass-1] = float32(snr / 10.0)

					obs.NaviSys = gnss.SYS_GLO
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_GLO_SIGN_G2_2P
					obs.PsV = this.gpsObs.CA[SYSGLN*MAXCHN+nGlonass-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}

				} else if svType == 7 || svType == 10 && nBD2 > 0 { // BD2
					//this.gpsObs.P2[SYSBD2*MAXCHN+nBD2-1] = 1.0*float64(lca)/math.Pow(2.0, 7) + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L2[SYSBD2*MAXCHN+nBD2-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D2[SYSBD2*MAXCHN+nBD2-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn2[SYSBD2*MAXCHN+nBD2-1] = float32(snr / 10.0)
				} else if svType == 3 && nGal > 0 { //E5B
					//this.gpsObs.P3[SYSGAL*MAXCHN+nGal-1] = 1.0*float64(lca)/math.Pow(2.0, 7) + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L3[SYSGAL*MAXCHN+nGal-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D3[SYSGAL*MAXCHN+nGal-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn3[SYSGAL*MAXCHN+nGal-1] = float32(snr / 10.0)
				}
			} else if blockType == 2 { // l5/E5A   (GPS/SBAS/Galileo E5A)
				if svType == 0 && nGps > 0 { // Gps
					//if blockType != 0 {
					//this.gpsObs.P3[nGps-1] = this.gpsObs.CA[nGps-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					////}
					//this.gpsObs.L3[nGps-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D3[nGps-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn3[nGps-1] = float32(snr / 10.0)

					obs.NaviSys = gnss.SYS_GPS
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_GPS_SIGN_L5_5I

					obs.PsV = this.gpsObs.CA[nGps-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				} else if svType == 7 || svType == 10 && nBD2 > 0 { // BDS
					//this.gpsObs.P5[SYSBD2*MAXCHN+nBD2-1] = 1.0*float64(lca)/math.Pow(2.0, 7) + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L5[SYSBD2*MAXCHN+nBD2-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D5[SYSBD2*MAXCHN+nBD2-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn5[SYSBD2*MAXCHN+nBD2-1] = float32(snr / 10.0)
					//this.gpsObs.channel[SYSBD2*MAXCHN+nBD2-1] = 1
				} else if svType == 3 && nGal > 0 { //E5A Galileo
					//this.gpsObs.P2[SYSGAL*MAXCHN+nGal-1] = this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L2[SYSGAL*MAXCHN+nGal-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D2[SYSGAL*MAXCHN+nGal-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn2[SYSGAL*MAXCHN+nGal-1] = float32(snr / 10.0)

					//fmt.Println(TrackType)
					obs.NaviSys = gnss.SYS_GAL
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_GAL_SIGN_E5A_5X

					obs.PsV = this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				}
			} else if blockType == 3 { // E5B (Galileo/BDS2/compass B2)
				//L2C
				//int ddBreak = 0;
				if svType == 7 || svType == 10 && nBD2 > 0 { // BDS
					//this.gpsObs.P2[SYSBD2*MAXCHN+nBD2-1] = this.gpsObs.CA[SYSBD2*MAXCHN+nBD2-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L2[SYSBD2*MAXCHN+nBD2-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D2[SYSBD2*MAXCHN+nBD2-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn2[SYSBD2*MAXCHN+nBD2-1] = float32(snr / 10.0)
					obs.NaviSys = gnss.SYS_BD
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_BDS_SIGN_B2_7I

					obs.PsV = this.gpsObs.CA[SYSBD2*MAXCHN+nBD2-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				} else if svType == 3 && nGal > 0 { //GALILEO  E5BI
					//this.gpsObs.P3[SYSGAL*MAXCHN+nGal-1] = this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L3[SYSGAL*MAXCHN+nGal-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D3[SYSGAL*MAXCHN+nGal-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn3[SYSGAL*MAXCHN+nGal-1] = float32(snr / 10.0)
					obs.NaviSys = gnss.SYS_GAL
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_GAL_SIGN_E5B_7X

					obs.PsV = this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				}
			} else if blockType == 4 { // E5A+B (Galileo)
				//int ddBreak = 0;
				if svType == 3 && nGal > 0 { //GALILEO  E5AI
					//this.gpsObs.P4[SYSGAL*MAXCHN+nGal-1] = this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L4[SYSGAL*MAXCHN+nGal-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D4[SYSGAL*MAXCHN+nGal-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn4[SYSGAL*MAXCHN+nGal-1] = float32(snr / 10.0)
					obs.NaviSys = gnss.SYS_GAL
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_GAL_SIGN_E5AB_8X

					obs.PsV = this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				}
			} else if blockType == 5 {
				if svType == 3 && nGal > 0 { //GALILEO  E6C
					//this.gpsObs.P5[SYSGAL*MAXCHN+nGal-1] = this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					//this.gpsObs.L5[SYSGAL*MAXCHN+nGal-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D5[SYSGAL*MAXCHN+nGal-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn5[SYSGAL*MAXCHN+nGal-1] = float32(snr / 10.0)

					obs.NaviSys = gnss.SYS_GAL
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_GAL_SIGN_E1_1X

					obs.PsV = this.gpsObs.CA[SYSGAL*MAXCHN+nGal-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				}
			} else if blockType == 6 {
				if svType == 7 || svType == 10 && nBD2 > 0 { // B1I
					obs.NaviSys = gnss.SYS_BD
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_BDS_SIGN_B1_2I
					if TrackType == 26 { //26:	BPSK(2)	(Beidou-2/Compass	B1)
						this.gpsObs.CA[SYSBD2*MAXCHN+nBD2-1] = 1.0 * float64(lca) / math.Pow(2.0, 7)
						if bOverFlow == 1 {
							this.gpsObs.CA[SYSBD2*MAXCHN+nBD2-1] += 33554431.0
						}
						obs.PsV = this.gpsObs.CA[SYSBD2*MAXCHN+nBD2-1]
					}
					//this.gpsObs.L1[SYSBD2*MAXCHN+nBD2-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)

					if svId <= 5 && svType == 7 {
						//this.gpsObs.L1[SYSBD2*MAXCHN+nBD2-1] = -1.0*float64(l64phase)/math.Pow(2.0, 15) + 0.5
						obs.PhV = -1.0*float64(l64phase)/math.Pow(2.0, 15) + 0.5
					}
					//this.gpsObs.D1[SYSBD2*MAXCHN+nBD2-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn1[SYSBD2*MAXCHN+nBD2-1] = float32(snr / 10.0)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				}
			} else if blockType == 7 { // && nBD2 > 0   B3I
				if svType == 7 || svType == 10 && nBD2 > 0 {
					obs.NaviSys = gnss.SYS_BD
					obs.SatId = byte(svId)
					obs.SigId = gnss.YOBS_BDS_SIGN_B3_6I
					if blockType != 26 {
						obs.PsV = this.gpsObs.CA[SYSBD2*MAXCHN+nBD2-1] + 1.0*float64(dlca)/math.Pow(2.0, 8)
					}
					//this.gpsObs.L3[SYSBD2*MAXCHN+nBD2-1] = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					//this.gpsObs.D3[SYSBD2*MAXCHN+nBD2-1] = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)
					//this.gpsObs.sn3[SYSBD2*MAXCHN+nBD2-1] = float32(snr / 10.0)
					obs.PhV = -1.0 * float64(l64phase) / math.Pow(2.0, 15)
					obs.Cnr = float32(snr / 10.0)
					obs.Doppler = 1.0 * float64(lDoppler) / math.Pow(2.0, 6)

					if !onobs(i+1, &obs, nil) {
						break
					}
				}
			}
		}
	}
	return nil
}
